/*
 * amplitude_scrambling.cpp
 *
 *  Created on: Apr 12, 2011
 *      Author: Paul Woelfel
 */

#include "crypto/amplitude_scrambling.h"
#include "logger.h"

const std::string CAmplitudeScrambling::sIniSectionName("AMPLITUDE_SCRAMBLING");

CAmplitudeScrambling::CAmplitudeScrambling(NAudioFormats::SStreamInfo ioStreamInfo)
	: CCryptoEngine(ioStreamInfo) {

	printl(0, __FILE__, "constructing %x %x", mMasterCipherStream, mSessionCipherStream);
}

CAmplitudeScrambling::~CAmplitudeScrambling() {

}

int CAmplitudeScrambling::dencrypt(double * pData, unsigned int pCount, bool bEncrypt) {
	if (mSessionCipherStream == NULL) {
		printl(LL_ERR, __FILE__, "CipherStream not initialized!");
		return 0;
	}
	std::string cipherStreamBytes;
	for (unsigned int i = 0; i < pCount; i++) {
		//		printl(0, __FILE__, "encrypting %u",i);
		mSessionCipherStream->getNext(&cipherStreamBytes, 2);
		short val = (((short) cipherStreamBytes[0]) << 8) | cipherStreamBytes[1];
		//		printl(0, __FILE__, "cipher stream bytes %x %x %d %d %x %d %f",(char)cipherStreamBytes[0], (char)cipherStreamBytes[1], cipherStreamBytes[0], cipherStreamBytes[1], val, val,((double)val) / 32768.0);
		double newValue = ((double) val) / 32768.0;

		// encryption
		// example 1: 0.3 + 0.8 = 1.1
		// example 2: -0.6 + -0.7 = -1.3

		// decryption
		// e1: -0.9 - 0.8 = -1.7
		// e2: 0.7 - -0.7 = 1.4

		if (bEncrypt) {
			pData[i] += newValue;
		} else {
			pData[i] -= newValue;
		}
		if (pData[i] > 1.0) {
			// enc: e1: -2.0 + 1.1 = -0.9
			// dec: e1: -2.0 + 1.4 = -0.6
			pData[i] = -2.0 + pData[i];
		}
		if (pData[i] < -1.0) {
			// enc: e2: 2.0 + - 1.3 = 0.7
			// dec: e2: 2.0 + - 1.3 = 0.7
			pData[i] = 2.0 + pData[i];
		}

	}
	if (bEncrypt) {
		return pCount;
	} else {
		return 0;
	}
}

int CAmplitudeScrambling::encrypt(double * pData, unsigned int pCount) {
	//	printl(0, __FILE__, "encrypt");
	return dencrypt(pData, pCount, true);
}

int CAmplitudeScrambling::decrypt(double * pData, unsigned int pCount) {
	//	printl(0, __FILE__, "decrypt");
	return dencrypt(pData, pCount, false);
}

int CAmplitudeScrambling::changeSettings() {
	printl(0, __FILE__, "changeSettings");
	int ret = CCryptoEngine::changeSettings();
	return ret;
}
